#include <ximera/system/application.hpp>
#include <ximera/logger.hpp>

#include <iostream>

struct InputTestHandler : ximera::system::AppHandler
{
	virtual void onStart(ximera::system::AppEventArgs& args)
    {
        try
        {
            _app = &args.app;
            testInput(args.app);
        }
        catch (ximera::Exception& e)
        {
            args.app.shouldClose(true);
            XIMERA_LOG() << e << std::endl;
        }
    }

private:
    ximera::system::Application* _app;

    void testInput(ximera::system::Application& app)
    {
        app.inputSystem()->keyboard()->onKeyUp() += 
            boost::bind(&InputTestHandler::keyboard_KeyUp, this, _1, _2);

        app.inputSystem()->keyboard()->onKeyDown() += 
            boost::bind(&InputTestHandler::keyboard_KeyDown, this, _1, _2);

        app.inputSystem()->mouse()->onMouseUp() += 
            boost::bind(&InputTestHandler::mouse_MouseUp, this, _1, _2);

        app.inputSystem()->mouse()->onMouseDown() += 
            boost::bind(&InputTestHandler::mouse_MouseDown, this, _1, _2);

        app.inputSystem()->mouse()->onAxisIntChange() += 
            boost::bind(&InputTestHandler::mouse_MouseMove, this, _1, _2, _3, _4, _5);
    }

    void keyboard_KeyDown(ximera::input::IKeyboard* sender, ximera::input::KeyCode const& keyCode)
    {
        std::cout << "onKeyDown: " << static_cast<ximera::UInt16>(keyCode.value) << "\n";
    }
                                          
    void keyboard_KeyUp(ximera::input::IKeyboard* sender, ximera::input::KeyCode const& keyCode)
    {
        if (keyCode == ximera::input::KeyCode::Escape)
            _app->shouldClose(true);

        std::cout << "onKeyUp " << static_cast<ximera::UInt16>(keyCode.value) << "\n";
    }

    void mouse_MouseMove(ximera::input::IDevice* sender, ximera::Byte axisIndex, ximera::Int16 lastValue, ximera::Int16 newValue, ximera::Int16 relValue)
    {
        std::cout << "onMouseMove: " << lastValue << ", " << newValue << ", " << relValue << "\n";
    }

    void mouse_MouseDown(ximera::input::IMouse* sender, ximera::input::MouseCode const& mouseCode)
    {
        std::cout << "onMouseDown: " << static_cast<ximera::UInt16>(mouseCode.value) << "\n";
    }

    void mouse_MouseUp(ximera::input::IMouse* sender, ximera::input::MouseCode const& mouseCode)
    {
        std::cout << "onMouseUp " << static_cast<ximera::UInt16>(mouseCode.value) << "\n";
    }
};

int main()
{
    using namespace ximera;

    try
    {
        XIMERA_LOG().stream(&std::wcout);

        system::AppSettings settings;
        settings[L"ximera.plugins.input"] = XIMERA_PLUGIN(L"XimeraDInput8");
        settings[L"ximera.plugins.graphics"] = XIMERA_PLUGIN(L"XimeraOgre");
        settings[L"ximera.ogre.showdialog"] = L"1";

        system::Application app(settings);

        InputTestHandler handler;
        app.addHandler(handler);

        return app.run();
    }                                          
    catch (ximera::Exception& e)
    {
        XIMERA_LOG() << e << std::endl;
    }
}
